home *** CD-ROM | disk | FTP | other *** search
/ Computer Select (Limited Edition) / Computer Select.iso / dobbs / v17n02 / undocwin.asc < prev    next >
Encoding:
Text File  |  1992-01-02  |  9.7 KB  |  338 lines

  1. _MAKING UNDOCUMENTED DOS CALLS FROM WINDOWS 3_
  2. by Paul Chui
  3.  
  4. [LISTING ONE]
  5.  
  6. #define NOCOMM
  7. #include <windows.h>
  8. #include <dos.h>
  9. #include <memory.h>
  10. #include "getdrvx.h"
  11.  
  12. #define CDS_SUBST (0x1000)
  13.  
  14. #define DOS3_CDS_SIZE  81
  15. #define DOS4_CDS_SIZE  88
  16. #define CDS_PATH       0x00
  17. #define CDS_FLAGS      0x43
  18. #define CDS_DPB        0x45
  19.  
  20. #define DPB_FATS       8
  21.  
  22. #define MK_FP(seg,ofs)  ((void far *) (((unsigned long)(seg) << 16) | (unsigned)(ofs)))
  23. #define _DS             GetDS()
  24.  
  25. /* Documented Windows functions not declared in WINDOWS.H */
  26. DWORD FAR PASCAL GlobalDosAlloc(DWORD dwBytes);
  27. WORD  FAR PASCAL GlobalDosFree(WORD wSelector);
  28.  
  29. /* Undocumented Windows functions */
  30. VOID FAR PASCAL SetSelectorBase(WORD wSelector, DWORD dwBase);
  31. VOID FAR PASCAL SetSelectorLimit(WORD wSelector, DWORD dwLimit);
  32.  
  33. /* Global Variables */
  34. WORD _wSelector;                // a data selector
  35.  
  36. /* Types */
  37. // DOS list of lists structure (for DOS 3.1 or better)
  38. typedef struct {
  39.     BYTE x[22];                 // (don't care)
  40.     BYTE far* cds;
  41.     BYTE xx[7];                 // (don't care)
  42.     BYTE lastdrive;
  43.     // ... the rest of DOS List of Lists
  44. } DOSLISTS;
  45.  
  46. // DPMI real-mode call structure
  47. typedef struct {
  48.     DWORD edi, esi, ebp, reserved, ebx, edx, ecx, eax;
  49.     WORD  flags, es, ds, fs, gs, ip, cs, sp, ss;
  50. } REALMODECALL;
  51.  
  52.  
  53. int GetDosVersionMajor(void)
  54. {
  55.     int     dosver;
  56.  
  57.     _asm    mov ah, 0x30;
  58.     _asm    int 0x21;
  59.     _asm    mov dosver, ax;
  60.  
  61.     return (BYTE)dosver;
  62. }
  63.  
  64. unsigned GetDS(void)
  65. {
  66.     _asm    mov ax, ds;
  67.     return;                 // return value in AX
  68. }
  69.  
  70.  
  71. /****************************************************************************
  72.     BOOL DPMI_RealModeInt(int intno, REALMODECALL far* r)
  73.  
  74.     PURPOSE: DPMI simulate real-mode interrupt function.  The
  75.     following is an excerpt from the DPMI Specification:
  76.  
  77.     PARAMETERS:
  78.         int   intno             real-mode interrupt to simulate
  79.         REALMODECALL far* r
  80.  
  81.     RETURNS: TRUE if interrupt is successful, FALSE on error
  82.  
  83.     NOTES: The following is an excerpt from INTEL's DPMI specs:
  84.  
  85.       To Call
  86.  
  87.            AX = 0300h
  88.            BL = Interrupt number
  89.            BH = Flags
  90.                 Bit 0  = 1 resets the interrupt controller and A20
  91.                 line
  92.                 Other flags reserved and must be 0
  93.            CX =  Number of  words to  copy from  protected mode to
  94.                 real-mode stack
  95.            ES:(E)DI = Selector:Offset of real-mode call structure
  96.  
  97.       Returns
  98.  
  99.            If function was successful:
  100.            Carry flag is clear.
  101.            ES:(E)DI =  Selector:Offset of modified real-mode call
  102.                 structure
  103.  
  104.            If function was not successful:
  105.            Carry flag is set.
  106. ****************************************************************************/
  107. BOOL DPMI_RealModeInt(int intno, REALMODECALL far* r)
  108. {
  109.     intno &= 0x00FF;        // reset high byte (flags)
  110.  
  111.     _asm {
  112.         push    di
  113.         mov     bx, intno   // flags | real-mode interrupt to call
  114.         mov     cx, 0       // don't copy anything from protected mode stack
  115.         les     di, r       // es:di -> real-mode call structure
  116.         mov     ax, 0x0300  // DPMI simulate real-mode interrupt function
  117.         int     0x31
  118.         pop     di
  119.         jc      error
  120.     }
  121.     return  TRUE;
  122.  
  123. error:
  124.     return  FALSE;
  125. }
  126.  
  127. /****************************************************************************
  128.     BYTE far* PMODE_ADDR(WORD wSel, BYTE far* RMODE_ADDR)
  129.  
  130.     PURPOSE: Get the Current Directory Structure
  131.  
  132.     PARAMETERS:
  133.         WORD wSel               A valid selector
  134.         BYTE far* RMODE_ADDR    A real mode address
  135.  
  136.     RETURNS: a protected-mode address of RMODE_ADDR
  137.  
  138.     NOTES: The base address of selector wSel is set to the segment of
  139.     RMODE_ADDR.
  140. *****************************************************************************/
  141. BYTE far* PMODE_ADDR(WORD wSel, BYTE far* RMODE_ADDR)
  142. {
  143.     SetSelectorBase(wSel, (DWORD) FP_SEG(RMODE_ADDR) << 4);
  144.     return  MK_FP(wSel, FP_OFF(RMODE_ADDR));
  145. }
  146.  
  147. /****************************************************************************
  148.     BYTE far* GetCDS(int nDrive)
  149.  
  150.     PURPOSE: Get the Current Directory Structure
  151.  
  152.     PARAMETERS: int nDrive          The drive to retrieve
  153.  
  154.     RETURNS: a real-mode pointer to the Current Directory Structure of
  155.     drive nDrive.
  156. *****************************************************************************/
  157. BYTE far* GetCDS(int nDrive)
  158. {
  159.     DOSLISTS far*   doslists;
  160.     REALMODECALL    r;
  161.  
  162.     // Get DOS list of lists (INT 21h, Function 52h)
  163.     _fmemset(&r, 0, sizeof(REALMODECALL));
  164.     r.eax = 0x5200;
  165.     if (!DPMI_RealModeInt(0x21, &r))
  166.         return  NULL;
  167.  
  168.     // Pointer to DOS list of lists is returned in ES:BX
  169.     doslists = (DOSLISTS far*)
  170.         PMODE_ADDR( _wSelector, MK_FP(r.es, LOWORD(r.ebx)) );
  171.  
  172.     if (GetDosVersionMajor() < 4)
  173.        return   doslists->cds + (nDrive * DOS3_CDS_SIZE);
  174.     else
  175.        return   doslists->cds + (nDrive * DOS4_CDS_SIZE);
  176. }
  177.  
  178. /****************************************************************************
  179.     BOOL isCDROM(int nDrive)
  180.  
  181.     PURPOSE: Tests if nDrive is a CD ROM drive
  182.  
  183.     PARAMETERS: int nDrive          The drive to test
  184.  
  185.     RETURNS: TRUE if nDrive is a CD ROM
  186.  *****************************************************************************/
  187. BOOL isCDROM(int nDrive)
  188. {
  189.     WORD     saveAX, saveBX;
  190.  
  191.     _asm     mov cx, nDrive;
  192.     _asm     mov ax, 0x150B;
  193.     _asm     int 0x2F;
  194.     _asm     mov saveAX, ax;
  195.     _asm     mov saveBX, bx;
  196.  
  197.     return   saveBX == 0xADAD && saveAX != 0;
  198. }
  199.  
  200.  
  201. /****************************************************************************
  202.     BOOL isSubstDrive(int nDrive)
  203.  
  204.     PURPOSE: Tests for drives created using the DOS SUBST command
  205.  
  206.     PARAMETERS: int nDrive          The drive to test
  207.  
  208.     RETURNS: TRUE if nDrive is a SUBST drive
  209. *****************************************************************************/
  210. BOOL isSubstDrive(int nDrive)
  211. {
  212.     BYTE far*   cds;        // Current Directory Structure
  213.     WORD        cds_flags;
  214.  
  215.     cds = PMODE_ADDR(_wSelector, GetCDS(nDrive));
  216.     cds_flags = *(WORD far*)(cds+CDS_FLAGS);
  217.     if (cds_flags &  (CDS_SUBST))
  218.         return  TRUE;
  219.  
  220.     return  FALSE;
  221. }
  222.  
  223. /****************************************************************************
  224.     BOOL isRamDrive(int nDrive)
  225.  
  226.     PURPOSE: Tests for Ram drives
  227.  
  228.     PARAMETERS: int nDrive          The drive to test
  229.  
  230.     RETURNS: TRUE if nDrive is a ram drive
  231.  
  232.     NOTES: This function tests to see if the drive has only one FAT.  It
  233.     is assumed that if this is true, then the drive must be a RAM drive.
  234. *****************************************************************************/
  235. BOOL isRamDrive(int nDrive)
  236. {
  237.     BYTE far*   cds;    // Current Directory Structure
  238.     BYTE far*   dpb;    // Drive Parameter Block
  239.  
  240.     cds = PMODE_ADDR(_wSelector, GetCDS(nDrive));
  241.  
  242.     dpb = *(BYTE far* far*)(cds+CDS_DPB);
  243.     dpb = PMODE_ADDR(_wSelector, dpb);
  244.  
  245.     if (*(dpb+DPB_FATS) == 1)
  246.         return  TRUE;
  247.  
  248.     return  FALSE;
  249. }
  250.  
  251. /****************************************************************************
  252.     WORD FAR PASCAL GetDriveTypeX(int nDrive)
  253.  
  254.     PURPOSE: Determines drive type
  255.  
  256.     PARAMETERS:
  257.         int   nDrive            The drive number. 0 = A:, 1 = B:,
  258.                                 2 = C:, 3 = D:, ...
  259.     RETURNS:
  260.         DRIVE_UNKNOWN           Unknown drive type
  261.         DRIVE_NOTEXIST          Drive does not exist
  262.         DRIVE_REMOVE            Removable (floppy) drive
  263.         DRIVE_FIXED             Fixed (hard) drive
  264.         DRIVE_REMOTE            Remote (network) drive
  265.         DRIVE_CDROM             CD ROM drive
  266.         DRIVE_RAM               Ram drive
  267.         DRIVE_SUBST             SUBST drive
  268. *****************************************************************************/
  269. WORD FAR PASCAL GetDriveTypeX(int nDrive)
  270. {
  271.     WORD    wDriveType;
  272.  
  273.     // Get a new selector, using the current DS as the prototype
  274.     _wSelector = AllocSelector(_DS);
  275.     SetSelectorLimit(_wSelector, 0xFFFF);
  276.  
  277.     wDriveType = GetDriveType(nDrive);
  278.  
  279.     if (isCDROM(nDrive))
  280.         wDriveType = DRIVE_CDROM;
  281.     else
  282.     if (wDriveType != DRIVE_REMOTE && isSubstDrive(nDrive))
  283.         wDriveType = DRIVE_SUBST;
  284.     else
  285.     if (isRamDrive(nDrive))
  286.         wDriveType = DRIVE_RAM;
  287.  
  288.     FreeSelector(_wSelector);
  289.     return  wDriveType;
  290. }
  291.  
  292. /****************************************************************************
  293.     BOOL FAR PASCAL GetCanonicalPath(LPSTR lpszRelPath, LPSTR lpszTruePath)
  294.  
  295.     PURPOSE: Resolve path string to canonical path string
  296.  
  297.     PARAMETERS:
  298.         LPSTR   lpszRelPath     Relative path string or directory name
  299.         LPSTR   lpszTruePath    Destination for canonical fully qualified
  300.                                 path
  301.     RETURNS:
  302.         TRUE if successful
  303. *****************************************************************************/
  304. BOOL FAR PASCAL GetCanonicalPath(LPSTR lpszRelPath, LPSTR lpszTruePath)
  305. {
  306.     BOOL        retval;
  307.     DWORD       dw;
  308.     WORD        wSelector;
  309.     WORD        wSegment;
  310.     LPSTR       lpszDosBuf;
  311.     REALMODECALL    r;
  312.  
  313.     dw = GlobalDosAlloc(128);
  314.     if (dw == NULL)
  315.         return FALSE;
  316.  
  317.     wSelector = LOWORD(dw);
  318.     wSegment  = HIWORD(dw);
  319.  
  320.     lpszDosBuf = MK_FP(wSelector, 0);
  321.     _fmemcpy(lpszDosBuf, lpszRelPath, 128);
  322.  
  323.     r.eax = 0x6000;
  324.     r.ds  = wSegment;
  325.     r.esi = 0;
  326.     r.es  = wSegment;
  327.     r.edi = 0;
  328.  
  329.     retval = DPMI_RealModeInt(0x21, &r);
  330.  
  331.     _fmemcpy(lpszTruePath, lpszDosBuf, 128);
  332.     GlobalDosFree(wSelector);
  333.  
  334.     return  retval;
  335. }
  336.  
  337.  
  338.